package com.elcom.roaming.module.collection;

import java.io.IOException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.elcom.roaming.common.StringCouple;
import com.elcom.roaming.common.config.ConfigModule;
import com.elcom.roaming.common.db.DBConfig;
import com.elcom.roaming.common.db.cache.CacheInsert;
import com.elcom.roaming.common.server.SMPPServer;
import com.elcom.roaming.common.util.match.ObjectInput;
import com.elcom.roaming.common.util.match.ObjectKey;
import com.elcom.roaming.common.util.match.ObjectValue;
import com.elcom.roaming.module.collection.match.UIMatchingObjects;
import com.elcom.util.app.AppReport;
import com.elcom.util.app.IApplication;
import com.elcom.util.app.IPCHandlerFactory;
import com.elcom.util.app.IPCShellController;
import com.elcom.util.app.MapManager;
import com.elcom.util.app.QueueManager;
import com.elcom.util.ipc.IPCHandler;
import com.elcom.util.map.BoundConcurrentMap;
import com.elcom.util.queue.BoundBlockingQueue;

public class ModuleCollectionInit implements IApplication {
	
	private Logger logger;
	private Logger loggerDB;
	private Logger loggerSMPP;
	private Logger loggerMonitor;
	private DBConfig dbConfig;
	private CacheInsert cacheInsert;
	private UIMatchingObjects matching;
	private SMPPServer server;

	/* *
	 * Monitor
	 */
	private String app_name;
	private IPCHandler app_ipc;
	private IPCShellController ipc_shell_ctrl;
	private QueueManager queue_manager;
	private MapManager map_manager;

	public ModuleCollectionInit() {
		logger = LoggerFactory.getLogger(ConfigModule.LOG_DEBUG_FLOW);
		loggerDB = LoggerFactory.getLogger(ConfigModule.LOG_DEBUG_DB);
		loggerSMPP = LoggerFactory
				.getLogger(ConfigModule.LOG_DEBUG_SMPP_SERVER);
		loggerMonitor = LoggerFactory
				.getLogger(ConfigModule.LOG_DEBUG_MONITOR);

		logger.info("Module Collection starting...");
		logger.info("DBConfig init...");
		dbConfig = new DBConfig(loggerDB);

		logger.info("CacheInsert init...");
		cacheInsert = new CacheInsert(loggerDB, "Cache-Insert", dbConfig.getDBQuery());

		logger.info("ObjectMatching init...");
		matching = new UIMatchingObjects(logger, "UI-Matching", cacheInsert);

		logger.info("SMPP Server init...");
		server = new SMPPServer(loggerSMPP, "SMPP-Server-Collection",
				ConfigModule.MODULE_CONFIG_SMPP_SERVER_FILE, matching);

	}

	public void run() {

		try {
			initMonitor();
			logger.info("Monitor started...");
		} catch (IOException e) {
			logger.error("Monitor init error.", e);
			return;
		}
	    
		new Thread(cacheInsert, cacheInsert.getName()).start();

		new Thread(matching, matching.getName()).start();
		
		try {
			server.start();
		} catch (Throwable e) {
			logger.error("SMPP Server start error.", e);
			return;
		}
	}

	private void initMonitor() throws IOException {
		app_name = "collection";
		app_ipc = IPCHandlerFactory.createIPCHandler(app_name);
		set_name(app_name);

		queue_manager = new QueueManager();
		map_manager = new MapManager();

		BoundBlockingQueue<ObjectInput> boundMatchingQueue = new BoundBlockingQueue<ObjectInput>(matching.getQueue());
		matching.setQueueName("MatchingQueue");
		boundMatchingQueue.setName("MatchingQueue");
		boundMatchingQueue.setMaxSize(ConfigModule.MATCHING_MAX_QUEUE_SIZE);
		queue_manager.add(boundMatchingQueue);
		
		BoundBlockingQueue<StringCouple> boundCacheQueue = new BoundBlockingQueue<StringCouple>(cacheInsert.getQueue());
		cacheInsert.setQueueName("CacheQueue");
		boundCacheQueue.setName("CacheQueue");
		boundCacheQueue.setMaxSize(ConfigModule.DB_MAX_QUEUE_SIZE);
		queue_manager.add(boundCacheQueue);

		BoundConcurrentMap<ObjectKey, ObjectValue> boundMatchingMap = new BoundConcurrentMap<ObjectKey, ObjectValue>(matching.getMap());
		matching.setMapName("MatchingMap");
		boundMatchingMap.setName("MatchingMap");
		boundMatchingMap.setMaxSize(ConfigModule.MATCHING_MAX_MAP_SIZE);
		map_manager.add(boundMatchingMap);
		
	    ipc_shell_ctrl = new IPCShellController(loggerMonitor, app_ipc, this);
	    ipc_shell_ctrl.execute();

	}

	@Override
	public int get_index() {
		return 0;
	}

	@Override
	public String get_info(String[] params) throws Throwable {
		return getReport();
	}

	private String getReport(){
		StringBuilder sbuf = new StringBuilder();
	    
	    AppReport.memory_report(sbuf);
	    queue_manager.queuesReport(sbuf);
	    map_manager.mapsReport(sbuf);
	    
	    return sbuf.toString();
	}
	
	@Override
	public String get_name() {
		return app_name;
	}

	@Override
	public void reload_config(String[] arg0) throws Throwable {
		ConfigModule.getInstance().reloadConfig();
		
		queue_manager.get(matching.getQueueName()).setMaxSize(ConfigModule.MATCHING_MAX_QUEUE_SIZE);
		queue_manager.get(cacheInsert.getQueueName()).setMaxSize(ConfigModule.DB_MAX_QUEUE_SIZE);
		map_manager.get(matching.getMapName()).setMaxSize(ConfigModule.MATCHING_MAX_MAP_SIZE);
	}

	@Override
	public void restart(String[] arg0) throws Throwable {
		// TODO Auto-generated method stub

	}

	@Override
	public void set_index(int index) {
		
	}

	@Override
	public void set_name(String arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void start(String[] arg0) throws Throwable {
		// TODO Auto-generated method stub
	}

	@Override
	public void stop(String[] arg0) throws Throwable {
		// TODO Auto-generated method stub
	}

}
